home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / lisp / kcl / akcl / kcl.lha / c / dguxsave.c < prev    next >
C/C++ Source or Header  |  1987-06-04  |  7KB  |  285 lines

  1. /*
  2. (C) Copyright Taiichi Yuasa and Masami Hagiya, 1984.  All rights reserved.
  3. */
  4.  
  5. #include "include.h"
  6.  
  7. struct nsection {
  8.     unsigned int logical_start;
  9.     unsigned int logical_length;
  10.     unsigned int file_start;
  11.     unsigned int file_length;
  12.     unsigned int file_reloc;
  13.     unsigned int file_reloc_length;
  14.     unsigned int attributes;
  15.     };
  16.  
  17. struct prformat {
  18.     unsigned short magic_number;       /*  magic                 */
  19.     unsigned short format_rev_number;  /*  format rev. number    */
  20.     unsigned short num_non_exec_sect;  /*  # of non-exec.  sects */
  21.     unsigned short num_exec_sect;      /*  # of executable sects */
  22.     struct nsection syshead;        /*  system header */
  23.     struct nsection symbolt;        /*  symbol table  */
  24.     struct nsection ds;             /*                */
  25.     struct nsection dl;             /*                */
  26.     struct nsection lt;             /*                */
  27.     struct nsection exec[2];        /*  two executable sections */
  28.     };
  29.  
  30. struct system_header {
  31.     unsigned int    start_pc;
  32.     unsigned int    stacks;
  33.     unsigned int    unlabeled;
  34.     unsigned int    time_stamp;
  35.     unsigned int    user_rev_number;
  36.     unsigned short    flags;
  37.     unsigned short    ntasks;
  38.     unsigned short    nchannels;
  39.     };
  40.  
  41. struct stack_register {
  42.     unsigned int fp;
  43.     unsigned int sp;
  44.     unsigned int sl;
  45.     unsigned int sb;
  46. };
  47.  
  48. #define NUM_ENVIRON 6
  49.  
  50. /*
  51.     saved_init copies arg and environment variables from top of data
  52.     segment to stack area and shrink the memory.
  53.  
  54.     When execed by system, arg and environment variables are as follows;
  55.  
  56.     break value --> |                    |
  57.                 +--------------------+
  58.             | environ array ptr  |--------+
  59.             +--------------------+        |
  60.             | argument array ptr |----+   |
  61.             +--------------------+    |   |
  62.     AC2 ---------->    | argument count     |    |   |
  63.             +--------------------+    |   |
  64.             |                    |    |   |
  65.     +============>    |    environment     |    |   |
  66.     !        |                    |    |   |
  67.     !        +--------------------+    |   |
  68.     !        |                    |    |   |
  69.     !    +====>    |     arguments      |    |   |
  70.     !    !    |                    |    |   |
  71.     !    !    +--------------------+    |   |
  72.     +====== ! =====    | environment array  |<-- | --+
  73.         !    +--------------------+    |
  74.         +======    |   argument array   |<---+
  75.             +--------------------+
  76.             |                    |
  77.  
  78. */
  79.  
  80.  
  81. void
  82. saved_init()
  83. {
  84.     char    *break_value;
  85.     char    *new_break_value;
  86.     char    *sbrk();
  87.     char    *old_start;    /* old data area start byte address */
  88.     char    *new_start;    /* new data area start byte address */
  89.     int    size;        /* data size */
  90.     int    *sp;        /* wide stack pointer */
  91.     int    i;
  92.  
  93.     int    argc;
  94.     char    **argv;
  95.     char    **envp;
  96.  
  97.     break_value = sbrk(0);
  98.  
  99.     argc = *((unsigned int *)break_value - 3);    /* arg count */
  100.     argv =
  101.      (char **)(*((unsigned int *)break_value - 2));    /* arg array ptr */
  102.     envp =
  103.      (char **)(*((unsigned int *)break_value - 1));    /* env array ptr */
  104.  
  105.     /*
  106.     old_start will be new break value after initialization.
  107.     */
  108.     new_break_value = old_start = (char *)&argv[0];
  109.  
  110.     /*
  111.     calc total space required. size is byte size and is multiple of 4
  112.     becase both break_value and argv[0] are double word boundary.
  113.     */
  114.     size = break_value - old_start;
  115.  
  116.     /* allocate space from stack. */
  117.     sp = getsp();                /* current stack pointer */
  118.     setsp(sp + size / 4);            /* extent stack */
  119.  
  120.     new_start = (char *)(sp + 1);
  121.  
  122.     blockmove(new_start, old_start, size);
  123.  
  124.     /*
  125.     set up new argv and new envp
  126.     */
  127.     argv = ((unsigned int)argv - (old_start - new_start) / 2);
  128.     envp = ((unsigned int)envp - (old_start - new_start) / 2);
  129.  
  130.     for (i = 0; i < argc; i++)
  131.         argv[i] -= (old_start - new_start);
  132.  
  133.     for (i = 0; i < NUM_ENVIRON; i++)
  134.         envp[i] -= (old_start - new_start);
  135.  
  136.     new_break_value =
  137.     (((unsigned int)new_break_value + PAGESIZE -1 ) / PAGESIZE) * PAGESIZE;
  138.  
  139.     brk(new_break_value);            /* shrink memory */
  140.  
  141.     main(argc, argv, envp);            /* call main routine */
  142.  
  143.     exit(0);
  144. }
  145.  
  146. filecpy(to, from, n)
  147. FILE *to, *from;
  148. int n;
  149. {
  150.     char    buffer[BUFSIZ];
  151.  
  152.     for (;;)
  153.         if (n > BUFSIZ) {
  154.             fread(buffer, BUFSIZ, 1, from);
  155.             fwrite(buffer, BUFSIZ, 1, to);
  156.             n -= BUFSIZ;
  157.         } else if (n > 0) {
  158.             fread(buffer, n, 1, from);
  159.             fwrite(buffer, n, 1, to);
  160.             break;
  161.         } else
  162.             break;
  163. }
  164.  
  165. memory_save(original_file, save_file)
  166. char *original_file, *save_file;
  167. {
  168.     int    s, n;
  169.     char    *data_start;
  170.     int    data_size;
  171.     int    orig_e0_start, orig_e0_len, orig_e1_start, orig_e1_len;
  172.     char    *p, *sbrk();
  173.     void    SVINIT();        /* special initializer */
  174.     FILE    *in, *out;
  175.     struct    prformat head;
  176.     struct    system_header system;
  177.     struct    stack_register sregs;
  178.     char    buffer0[BUFSIZ], buffer1[BUFSIZ];
  179.     char    buffer[BUFSIZ];
  180.  
  181.     out = fopen(save_file, "w+");
  182.     if (out == NULL) FEerror("Can't open output file.", 0);
  183.     setbuf(out, buffer0);
  184.  
  185.     in = fopen(original_file, "r");
  186.     if (in == NULL) FEerror("Can't open original KCl.", 0);
  187.     setbuf(in, buffer1);
  188.  
  189.     /*
  190.         First, we must build file header. File header is built
  191.         by modifying the origial program's file header.
  192.     */
  193.     fread((char *)&head, sizeof(struct prformat), 1, in);
  194.  
  195.     orig_e0_start = head.exec[0].file_start;
  196.     orig_e0_len = head.exec[0].file_length;
  197.     orig_e1_start = head.exec[1].file_start;
  198.     orig_e1_len = head.exec[1].file_length;
  199.  
  200.     data_size = sbrk(0) - (char *)034000000000;
  201.     head.exec[1].file_start = (orig_e0_start + data_size + 02000) & ~01777;
  202.     s = head.exec[1].file_start - orig_e1_start;
  203.     head.symbolt.file_start += s;
  204.     head.ds.file_start += s;
  205.     head.dl.file_start += s;
  206.     head.lt.file_start += s;
  207.     head.exec[0].logical_length += (s / 2);
  208.     head.exec[0].file_length = data_size;
  209.  
  210.     fwrite((char *)&head, sizeof(struct prformat), 1, out);    /* header */
  211.  
  212.     /*
  213.         Start_pc should be changed to special initializer for 
  214.         a saved program.
  215.     */
  216.     fread((char *)&system, sizeof(system), 1, in);
  217.     system.start_pc = &SVINIT;
  218.     system.stacks = *(unsigned int *)016000000024 -
  219.                 *(unsigned int *)016000000026;
  220.     fwrite((char *)&system, sizeof(system), 1, out);
  221.  
  222.     /*
  223.         gap
  224.     */
  225.     filecpy(out, in, orig_e0_start - sizeof(struct prformat)
  226.         - sizeof(struct system_header));
  227.  
  228.     /*
  229.         data segment
  230.     */
  231.     for (p = (char *)034000000000, n = data_size;
  232.          ;p += BUFSIZ, n -= BUFSIZ)
  233.         if (n > BUFSIZ)
  234.             fwrite(p, BUFSIZ, 1, out);
  235.         else if (n > 0) {
  236.             fwrite(p, n, 1, out);
  237.             break;
  238.         } else
  239.             break;
  240.  
  241.     /*
  242.         gap
  243.     */
  244.     zero(buffer, BUFSIZ);
  245.     fwrite(buffer,
  246.       head.exec[1].file_start - (head.exec[0].file_start + data_size),
  247.       1,
  248.       out);
  249.  
  250.     /*
  251.         text segment
  252.     */
  253.     fseek(in, orig_e1_start, 0);
  254.     filecpy(out, in, head.exec[1].file_length);
  255.  
  256.     /*
  257.         others
  258.     */
  259.     filecpy(out, in, head.symbolt.file_length);
  260.     filecpy(out, in, head.ds.file_length);
  261.     filecpy(out, in, head.dl.file_length);
  262.     filecpy(out, in, head.lt.file_length);
  263.  
  264.     fclose(out);
  265.     fclose(in);
  266.  
  267.     chmod(save_file, 0777);        /* change file mode */
  268. }
  269.  
  270. Lsave()
  271. {
  272.     char    filename[256];
  273.  
  274.     check_arg(1);
  275.     check_type_or_pathname_string_symbol_stream(&vs_base[0]);
  276.     coerce_to_filename(vs_base[0], filename);
  277.     memory_save(kcl_self, filename);
  278.     exit(0);
  279. }
  280.  
  281. init_dguxsave()
  282. {
  283.     make_function("SAVE", Lsave);
  284. }
  285.